class DB {
  /**
   * 构造函数
   * @param {Object} config 传入数据库名、版本号
   */
  constructor(
    config = {
      dbName: "",
      dbVersion: 1,
    }
  ) {
    this.dbName = config.dbName;
    this.dbVersion = config.dbVersion;
    // indexDB 返回的操作数据库的实例
    this.dbInstance = null;
  }
  /**
   * 初始化数据库连接
   * @param {Array} objectStoreList 新建的表集合
   */
  initDb(objectStoreList) {
    return new Promise((resolve, reject) => {
      // 打开数据库
      const dbRequest = window.indexedDB.open(this.dbName, this.dbVersion);
      // 打开失败时
      dbRequest.onerror = (err) => {
        reject(err);
      };
      // 打开成功时
      dbRequest.onsuccess = (res) => {
        // 获取到数据库实例
        this.dbInstance = dbRequest.result;
        resolve(this.dbInstance);
      };
      // 首次打开数据库 或 数据库版本号变更时
      dbRequest.onupgradeneeded = async (res) => {
        console.log("监听到数据库版本号升级!", res);
        // 获取到数据库实例
        this.dbInstance = res.target.result;
        // 拿到当前事务
        let transaction = res.target.transaction;
        // 创建表
        let promiseArr = objectStoreList.map((i) => {
          return this.createObjectStore(
            i.storeName,
            i.storeConfig,
            i.storeIndex
          );
        });
        Promise.all(promiseArr).then((res) => {
          console.log("所有的表都新建成功了!", res, res.length);
          // 这里必须等数据库升级、创建表这个事务执行完毕
          transaction.oncomplete = () => {
            resolve(this.dbInstance);
          };
        });
      };
    });
  }
  /**
   * 判断数据库是否连接成功
   */
  IsDeInitSuccess() {
    // 有数据库的实例就证明链接成功
    return !!this.dbInstance;
  }
  /**
   * 判断表是否存在
   * @param {String} storeName 表名
   */
  hasObjectStore(storeName) {
    // 传入表名判断是否存在该张表
    return this.dbInstance.objectStoreNames.contains(storeName);
  }
  /**
   * 新建一张表
   * @param  {String} storeName 表名
   * @param  {Object} storeConfig 表配置信息
   * @param  {Array} storeIndex 表的索引
   */
  createObjectStore(storeName, storeConfig = {}, storeIndex = []) {
    return new Promise((resolve, reject) => {
      if (!this.IsDeInitSuccess()) {
        reject("数据库未连接成功,无法进行后续操作!");
      }
      // 已存在时直接 resolve 目前没有找到合适的方法更新表的字段
      if (this.hasObjectStore(storeName)) {
        resolve(`${storeName} 表已存在`);
      }
      // 创建表
      let objectStore = this.dbInstance.createObjectStore(
        storeName,
        storeConfig
      );
      // 指定这张表的索引 （可以理解为字段）
      storeIndex.map((i) => {
        objectStore.createIndex(i.name, i.key, i.config);
      });
      resolve(objectStore);
    });
  }
  /**
   * 新建一个事务
   * @param {String} storeName 表名
   * @param {String} type 操作类型 默认读写
   */
  createTransaction(storeName, type = "readwrite") {
    // 打开一张表增删改查等都需要事务这个概念
    return this.dbInstance.transaction([storeName], type);
  }
  /**
   * 获取一张表的实例
   * @param {String} storeName
   */
  getObejctStore(storeName) {
    if (!this.IsDeInitSuccess) {
      throw new Error("获取表实例失败,原因:未成功连接数据库!");
    }
    // 创建事务并打开一张表
    return this.createTransaction(storeName).objectStore(storeName);
  }
}

export default DB;
